package com.sl.core.engine.data.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.sl.core.engine.data.ProcessCompContextService;
import com.sl.core.engine.step.rowfrom.ProcessCompPutRowFrom;
import com.sl.core.engine.step.rowfrom.ProcessCompPutRowFromConfig;
import com.sl.core.engine.utils.BeanUtil;
import org.apache.hop.pipeline.transform.BaseTransformData;

import java.util.Collection;
import java.util.List;

public abstract class AbstractProcessCompContext extends BaseTransformData implements ProcessCompContextService {

    private Object inputData;

    private Object resultData;

    private Integer size = 1;

    public void setSize(Integer size) {
        this.size = size;
    }

    public AbstractProcessCompContext() {
    }

    public AbstractProcessCompContext(Integer size) {
        this.size = size;
    }

    public Object getInput(boolean isList) {
        Object o = get(inputData, isList);
        inputData = null;
        return o;
    }

    public Object get(Object data, boolean isList) {
        Object temp = data;
        if (ObjectUtil.isNull(temp)) {
            return null;
        }
        if (!(temp instanceof Collection<?>) && isList) {
            temp = Lists.newArrayList(temp);
        }
        return temp;
    }

    public Object getResult(boolean isList) {
        Object o = get(resultData, isList);
        resultData = null;
        return o;
    }

    public void addInput(Object pp) {
        inputData = add(pp, inputData);
    }

    public void addInput(Object pp, Class c) {
        inputData = add(pp, inputData);
    }

    public void addInput(Object pp, Class c, String stepName) {

        if (ProcessCompPutRowFrom.class.isAssignableFrom(c)) {
            addFrom(pp, stepName);
        } else {
            inputData = add(pp, inputData);
        }
    }

    private void addFrom(Object pp, String stepName) {
        if (ObjectUtil.isNull(inputData)) {
            inputData = new ProcessCompPutRowFrom();
        }
        ProcessCompPutRowFrom pc = BeanUtil.convert(inputData);
        List<ProcessCompPutRowFromConfig> configList = pc.getConfigList();
        if (ObjectUtil.isNull(configList)) {
            configList = Lists.newArrayList();
            pc.setConfigList(configList);
        }
        ProcessCompPutRowFromConfig processCompPutRowFromConfig = configList.stream().filter(v -> v.getFromTransformName().equals(stepName)).findFirst().orElse(null);

        if (ObjectUtil.isNull(processCompPutRowFromConfig)) {
            processCompPutRowFromConfig = new ProcessCompPutRowFromConfig(stepName, null);
            configList.add(processCompPutRowFromConfig);
        }
        Object data = processCompPutRowFromConfig.getData();
        if(ObjectUtil.isNull(data)){
            data = Lists.newArrayList();
            processCompPutRowFromConfig.setData(data);
        }
        List list = BeanUtil.convert(data);
        list.add(pp);
    }


    private Object add(Object pp, Object data) {
        if (ObjectUtil.isNull(pp)) {
            return pp;
        }
        if (ObjectUtil.isNull(data)) {
            data = pp;
            return data;
        }
        List<Object> list = Lists.newArrayList();

        if (data instanceof List d) {
            list.addAll(d);
        } else {
            list.add(data);
        }
        if (pp instanceof List d) {
            list.addAll(d);
        } else {
            list.add(pp);
        }
        return list;
    }

    public boolean isCut(Boolean isEnd) {
        if (ObjectUtil.isNull(inputData)) {
            return false;
        }

        if (size == 1) {
            return true;
        }
        if (BooleanUtil.isTrue(isEnd)) {
            return true;
        }
        if (inputData instanceof Collection<?> cut) {
            if (cut.size() >= size) {
                return true;
            }
        }
        return false;
    }

    public void addResult(Object r) {
        resultData = add(r, resultData);
    }
}
